#include "Common.h"
#include "ShapeHelper.h"
#include "Shader.h"
#include "Material.h"
#include "MaterialManager.h"
#include "Render.h"
#include "MeshBuilder.h"


void ShapeHelper::Define(ShaderDefineMap* defineMap)
{
	defineMap->AddVariable("float3 DiffuseColor;");
	defineMap->AddVariable("float3 EmissiveColor;");
	defineMap->AddVariable("float3 SpecularColor;");

	defineMap->AddDefine("MAT_DIFFUSE", "DiffuseColor");
	defineMap->AddDefine("MAT_EMISSIVE", "EmissiveColor");
	defineMap->AddDefine("MAT_SPECULAR", "SpecularColor");
}

Material* ShapeHelper::BuildShapeMaterial(const std::string& name)
{
	Material* material = MaterialManager::Instance().Create(name);
	if (material == NULL)
		return NULL;

	material->setDefineType(ShapeHelper::Define);
	material->Compile();

	MaterialParameter& param = material->getMaterialParam();
	param.Vector4Params.push_back(Vector4Param("DiffuseColor", Vector4(0.8f, 0.8f, 0.8f, 1.0f)));
	param.Vector4Params.push_back(Vector4Param("EmissiveColor", Vector4()));
	param.Vector4Params.push_back(Vector4Param("SpecularColor", Vector4()));

	return material;
}

const Material* ShapeHelper::DefaultShapeMaterial()
{
	return MaterialManager::Instance().getShapeMaterial();
}
	
void ShapeHelper::BuildBox(const std::string& name, float width, float length, float height)
{
	MeshBuilder builder;
	builder.Begin(name, 4);

	unsigned int Idx = 0;

	// top
	builder.AddVertex(Vector3(0,	 height, 0), Vector2(0, 0), Vector3::UnitY);
	builder.AddVertex(Vector3(width, height, 0), Vector2(1, 0), Vector3::UnitY);
	builder.AddVertex(Vector3(width, height, length), Vector2(1, 1), Vector3::UnitY);
	builder.AddVertex(Vector3(0,	 height, length), Vector2(0, 1), Vector3::UnitY);
	builder.AddTriangle(Idx + 0, Idx + 2, Idx + 1);
	builder.AddTriangle(Idx + 0, Idx + 3, Idx + 2);
	Idx += 4;

	// bottom
	builder.AddVertex(Vector3(0, 0, 0), Vector2(0, 0), -Vector3::UnitY);
	builder.AddVertex(Vector3(width, 0, 0), Vector2(1, 0), -Vector3::UnitY);
	builder.AddVertex(Vector3(width, 0, length), Vector2(1, 1), -Vector3::UnitY);
	builder.AddVertex(Vector3(0, 0, length), Vector2(0, 1), -Vector3::UnitY);
	builder.AddTriangle(Idx + 0, Idx + 1, Idx + 2);
	builder.AddTriangle(Idx + 0, Idx + 2, Idx + 3);
	Idx += 4;

	// left
	builder.AddVertex(Vector3(0, 0,		0), Vector2(0, 0), -Vector3::UnitX);
	builder.AddVertex(Vector3(0, height,0), Vector2(1, 0), -Vector3::UnitX);
	builder.AddVertex(Vector3(0, height,length), Vector2(1, 1), -Vector3::UnitX);
	builder.AddVertex(Vector3(0, 0,		length), Vector2(0, 1), -Vector3::UnitX);
	builder.AddTriangle(Idx + 0, Idx + 2, Idx + 1);
	builder.AddTriangle(Idx + 0, Idx + 3, Idx + 2);
	Idx += 4;

	// right
	builder.AddVertex(Vector3(width, 0,		0), Vector2(0, 0), Vector3::UnitX);
	builder.AddVertex(Vector3(width, height,0), Vector2(1, 0), Vector3::UnitX);
	builder.AddVertex(Vector3(width, height,length), Vector2(1, 1), Vector3::UnitX);
	builder.AddVertex(Vector3(width, 0,		length), Vector2(0, 1), Vector3::UnitX);
	builder.AddTriangle(Idx + 0, Idx + 1, Idx + 2);
	builder.AddTriangle(Idx + 0, Idx + 2, Idx + 3);
	Idx += 4;

	// front
	builder.AddVertex(Vector3(0, 0,		length), Vector2(0, 0),  Vector3::UnitZ);
	builder.AddVertex(Vector3(0, height,length), Vector2(1, 0),  Vector3::UnitZ);
	builder.AddVertex(Vector3(width, height,length), Vector2(1, 1),  Vector3::UnitZ);
	builder.AddVertex(Vector3(width, 0,		length), Vector2(0, 1),  Vector3::UnitZ);
	builder.AddTriangle(Idx + 0, Idx + 2, Idx + 1);
	builder.AddTriangle(Idx + 0, Idx + 3, Idx + 2);
	Idx += 4;
	
	// back
	builder.AddVertex(Vector3(0, 0,		0), Vector2(0, 0), -Vector3::UnitZ);
	builder.AddVertex(Vector3(0, height,0), Vector2(1, 0), -Vector3::UnitZ);
	builder.AddVertex(Vector3(width, height,0), Vector2(1, 1), -Vector3::UnitZ);
	builder.AddVertex(Vector3(width, 0,		0), Vector2(0, 1), -Vector3::UnitZ);
	builder.AddTriangle(Idx + 0, Idx + 1, Idx + 2);
	builder.AddTriangle(Idx + 0, Idx + 2, Idx + 3);
	Idx += 4;

	builder.End();
}